package com.tencent.welink.iot;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.leaf.lowcode.utils.RegularInstance;
import com.tencent.welink.sm.SM4Utils;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttCallbackExtended;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;

import java.util.ArrayList;

/**
 * Created by junchihe on 2020/6/11.
 */
public class MQTTMessageReceive implements MqttCallbackExtended {
    private static final Logger log = LogManager.getLogger(MQTTMessageReceive.class);
    private final LoginData loginData;
    private WelinkMqtt welinkMqtt;
    private boolean change = false;
    public MQTTMessageReceive(WelinkMqtt welinkMqtt){
        this.welinkMqtt = welinkMqtt;
        loginData = welinkMqtt.loginData;
    }

    public void connectionLost(Throwable cause) {
        // 连接丢失后，一般在这里面进行重连
        log.error("连接断开，可以做重连");
        log.error(cause.toString());

    }

    public void deliveryComplete(IMqttDeliveryToken token) {
        log.info("deliveryComplete---------" + token.isComplete());
    }

    private void changeToken(){
        log.info("chanage token {} from to {} token",this.loginData.lastHttpToken,this.loginData.httpToken);
        this.loginData.lastHttpToken = this.loginData.httpToken;
        this.loginData.lastRan = this.loginData.ran;
        this.loginData.lastSm4IV = this.loginData.sm4IV;
        this.change = true;
        log.info("after chanage token {} from to {} token",this.loginData.lastHttpToken,this.loginData.httpToken);
    }

    private void caseJsonProcess(JSONObject jsonObject) {
        int datapoint = jsonObject.getIntValue("datapoint");
        if(datapoint == 10000084) {
            log.info("video command here ...");
            /**
             * {"sm4_vector":"fEMVTDdskElB7lN9","stream_token":"Xwz43pHT","stream_id":0,
             * "stream_en_key":"a0PtcFylyWnSh1UY","server_ip":"118.126.104.117","server_port":9001,
             * "cmd":"StartPushStream","encrypt_version":4,"server_innerip":"10.3.32.12"}
             */
            JSONObject jsonValue =  JSONObject.parseObject(jsonObject.getString("value"));

            long din=  Long.parseLong((String)jsonObject.get("subDin"));
           // if(StringUtils.isNotEmpty(cmd)&&cmd.equalsIgnoreCase("LocalRecordStream")){
//                this.handleVideoCmd(din,jsonValue);
          //  }
        } else if(datapoint == 30006) {
            log.info("sub device list received ...");
            this.handleReceiveSubDeviceList(jsonObject);
        }else if(datapoint == -1) {
            log.info("device passthrough data...");
            JSONObject jsonValue =  JSONObject.parseObject(jsonObject.getString("value"));
            long din=  Long.parseLong((String)jsonObject.get("subDin"));
            this.handleDevicePassThrough(din,jsonValue);
        }else if(datapoint == 100) {
            log.info("device receive data =====================  ");
            JSONObject jsonValue =  JSONObject.parseObject(jsonObject.getString("value"));
            log.info("jsonValue"+jsonValue);
        }else  {
            log.info("receive data,but have nothing to do here: ");
            log.info("jsonValue"+jsonObject);
        }
    }

    private void decryptPayLoad(MqttMessage mqttMessage) throws Exception {
        //mqttMessage.getPayload();
        LoginData ld = loginData.load();
        try {
            String message = new String(SM4Utils.decryptDataCBC(mqttMessage.getPayload(), ld.ran, ld.sm4IV), "utf-8");
            log.info(System.currentTimeMillis() + "接收消息内容 : " + message);

            JSONObject jsonObject = JSONObject.parseObject(message);
            caseJsonProcess(jsonObject);

            if (!change)
                changeToken();
        }catch (Exception e) {
            log.error(e);
            try {
                String message = new String(SM4Utils.decryptDataCBC(mqttMessage.getPayload(), ld.lastRan, ld.lastSm4IV), "utf-8");
                JSONObject jsonObject = JSONObject.parseObject(message);
                caseJsonProcess(jsonObject);
                log.info(System.currentTimeMillis() + "接收消息内容by last : " + message);
            }catch (Exception e1){
                log.error(e1);
            }
        }
    }

    public void messageArrived(String topic, MqttMessage message) throws Exception {
        // subscribe后得到的消息会执行到这里面
        log.info(System.currentTimeMillis()+"接收消息主题 : " + topic);
        log.info(System.currentTimeMillis()+"接收消息Qos : " + message.getQos());
        try {
            decryptPayLoad(message);
            if (!change && System.currentTimeMillis() - this.loginData.time >=3600000)
                changeToken();
        }catch (Exception e) {
            log.error(e);
        }
    }


    /**
     * 处理接受子设备列表
     * @param jsonObject
     */
    public void handleReceiveSubDeviceList(JSONObject jsonObject){
        /**
         * [{"nvrusername":"","ipc_manufacturer":"","ip":"","nvrpassword":"","din":"300000000000070688",
         * "channel":0,"pid":1701000276,"rtspuri":"","nvrport":0,"manufacturer":"lim","password":"123",
         * "stream_from":"","wId":"139df654-a6f8-4dbf-8071-dafac7c943d9","nvrip":"","subdin":"0","port":0,
         * "nvr_manufacturer":"","sn":"1701000276lim","username":"admin"},
         * {"nvrusername":"","ipc_manufacturer":"","ip":"","nvrpassword":"","din":"300000000000070689",
         * "channel":0,"pid":1701000276,"rtspuri":"","nvrport":0,"manufacturer":"lim","password":"admin",
         * "stream_from":"","wId":"08338d42-75f9-4cde-ab27-7272fd9b0826","nvrip":"","subdin":"0","port":0,
         * "nvr_manufacturer":"","sn":"1701000276lim2","username":"123"}]
         */
        String deviceArray = (String) jsonObject.get("value");
        System.out.println("egularInstance.subDeviceDTOList======");
        if(StringUtils.isNotEmpty(deviceArray)){
            JSONArray jsonArray = JSONArray.parseArray(deviceArray);
            ArrayList<SubDeviceDTO> deviceDTOS = (ArrayList<SubDeviceDTO>) jsonArray.toJavaList(SubDeviceDTO.class);
            this.welinkMqtt.subDeviceDTOList = deviceDTOS;
            RegularInstance.subDeviceDTOList = deviceDTOS;  //存入静态变量或写入数据库
        }
    }

    /**
     * 设备透传
     * @param subDin
     * @param jsonValue
     */
    public void handleDevicePassThrough(long subDin, JSONObject jsonValue){
        try {
            int datapoint = jsonValue.getIntValue("datapoint");
            String value = jsonValue.getString("value");
            welinkMqtt.sendMessage(loginData.ran,loginData.sm4IV,datapoint,subDin,value,"report");
        } catch (MqttException e) {
            e.printStackTrace();
        }
    }

//    /**
//     * 处理推流
//     * @param jsonObject
//     */
//    public void handleVideoCmd(long din, JSONObject jsonObject){
//        /**
//         * {"sm4_vector":"fEMVTDdskElB7lN9","stream_token":"Xwz43pHT","stream_id":0,
//         * "stream_en_key":"a0PtcFylyWnSh1UY","server_ip":"118.126.104.117","server_port":9001,
//         * "cmd":"StartPushStream","encrypt_version":4,"server_innerip":"10.3.32.12"}
//         *
//         * o.put("din", din);
//         o.put("subdin", 0);
//         o.put("stream_id", streamId);
//         o.put("stream_token",token);
//         o.put("server_ip",videoServerJo.get("outip"));
//         o.put("server_innerip",videoServerJo.getString("videoPushServerIp"));
//         o.put("server_port",videoServerJo.getInteger("port"));
//         o.put("cmd", "StartPushStream");
//         o.put("timeStamp",System.currentTimeMillis());
//         *
//         */
//        int subdin= 0;
//        int streamId= jsonObject.getIntValue("stream_id");
//        String key=din+"_"+subdin +"_"+streamId;
//        String stream_en_key=  jsonObject.getString("stream_en_key");
//        String sm4Vector= jsonObject.getString("sm4_vector");
//        String token=  jsonObject.getString("stream_token");
//        String host=  jsonObject.getString("server_ip");
//        String innerip = jsonObject.getString("server_innerip");
//        int port= jsonObject.getIntValue("server_port");
//        String cmd = jsonObject.getString("cmd");
//
//
//        String recordHandler =  (String) jsonObject.get("recordHandler");
//      //  String filePath = NVRSenderClient.class.getResource("/").getPath()+"default.mtav";
//       // String filePath = "D:\\04src\\welink\\welink-sdk\\welink-java-sdk\\src\\main\\resources\\default.mtav";
//
//        String filePath =  NVRSenderClient.class.getResource("/"+ BussinessConfig.videoFileName+".mtav").getPath();
//        if(!"/".equals(File.separator)) {
//            filePath = StringUtils.replace(StringUtils.strip(filePath,"/"), "/", File.separator);
//        }
//        log.info("camera file path is {} !",filePath);
//        int version =  jsonObject.getIntValue("encrypt_version");
//        if("LocalRecordStream".equalsIgnoreCase(cmd)) {
//            try {
//                new NVRSenderClient().connect(port, host, din, subdin, streamId, recordHandler, token, stream_en_key, sm4Vector, filePath, version);
//            } catch (Exception e) {
//                log.error(e);
//            }
//        } else if("StartPushStream".equalsIgnoreCase(cmd)) {
//
//            if(IOTLogin.DO_CONNECTED.get(key)==null){
//                log.info("camrea {} start push to welink",key);
//                IOTLogin.DO_CONNECTED.put(key,true);
//                new PBPushClientRunnable(din, subdin, streamId, key, stream_en_key, sm4Vector, token, host, port, filePath).run();
//            }
//        } else if("ClosePushStream".equalsIgnoreCase(cmd)) {
//            CameraDataSendHandler cameraDataSendHandler = IOTLogin.CHANNEL_CONNECT_MAP.get(key);
//            if(cameraDataSendHandler != null) cameraDataSendHandler.disConnect();
//            log.info("close {} camera video stream!",key);
//        }
//
//    }

    @Override
    public void connectComplete(boolean b, String s) {
        try {
            int[] Qos = {1};
            String[] serverTopic = {this.welinkMqtt.TOPIC};
            this.welinkMqtt.client.subscribe(serverTopic, Qos);
        } catch (Exception e){
            log.error(e);
        }
    }
}
